#ifndef QueryProcessor_GUARD
#define QueryProcessor_GUARD
#include "SPA_Data_Types.h"
#include "PKB\TABLES\StatTable.h"
#include "PKB\TABLES\VarTable.h"
#include "PKB\TABLES\ProcTable.h"
#include "PKB\TABLES\ModifyVarTable.h"
#include "PKB\TABLES\ModifyStatTable.h"
#include "PKB\TABLES\UsesStatTable.h"
#include "PKB\TABLES\UsesVarTable.h"
#include "PKB\TABLES\ModifyProcTable.h"
#include "PKB\TABLES\UsesProcTable.h"
#include "PKB\TABLES\CallsTable.h"
#include "PKB\TABLES\AuxilaryTable.h"
#include<string>
#include<list>
#include<cstring>
#include <stack>

#include <boost\algorithm\string.hpp>

using namespace std;

class QueryProcessor{
private:
	StatTable* stat;
	VarTable* var;
	ProcTable* proc;
	ModifyVarTable* modvar;
	ModifyStatTable* modstat;
	UsesVarTable* usevar;
	UsesStatTable* usestat;
	ModifyProcTable* modproc;
	UsesProcTable* useproc;
	CallsTable* call;
	AuxAffects* auxAffects;
	
	INTEGER getOperatorPrecedence(const char c);
	BOOLEAN isOperator(char c);
	BOOLEAN isReducible ( STRING expression );
public:
	QueryProcessor();

	typedef struct affectsNode {
		STATEMENT_INDEX stmtID;
		BOOLEAN isVisited;
	};

    int join(vector<vector<int>>&result, vector<int>&s);
	int getCallStmt(vector<int>&result, PROC_INDEX);
	int getPattern(vector<int>& result,vector<int>& varresult, Argument arg1, Argument arg2, PAT_Argument patarg2);
	BOOLEAN matchExprPattern( STATEMENT_INDEX conditional_stmt_id, VAR_INDEX var_keyIndex );
	BOOLEAN matchExprPattern( STATEMENT_INDEX assignment_stmt_id, STRING expr_key, PatternPos pos );
	int getAll(list<string>&,vector<QRYSTATEMENT_TYPE> type, vector<WITHATTRIBUTE_TYPE> attribute); //for tuple
	int getAll(vector<int>& s, int type); //for single
	int getWith(vector<int>& result1, vector<int>& result2, Argument arg1, Argument arg2);
	//Functions to get the information about the entity in the query
	int validateEntity(int num, int type); //validate stmtnum and constant
	int getEntityTypeIndex(string e, int& type);
	int getEntityIndex(string e,int type);
	string getEntityName(int index,int type);

    //Functions to get follows and follows*
	int getFollow(vector<int>&, vector<int>&, Argument, Argument);
	int getFollowT(vector<int>&, vector<int>&, Argument, Argument);
	int getFollowing(vector<int>&, vector<int>&,int , int, int, int);
	int getFollowingT(vector<int>&, vector<int>&, int , int, int, int);
	int getFollowedby(vector<int>&, vector<int>&, int , int, int);
	int getFollowedbyT(vector<int>&, vector<int>&,int , int, int);

	//Functions to get Parent and Parent*
	int getParent(vector<int>&,vector<int>&, Argument, Argument);
	int getParentT(vector<int>&,vector<int>&, Argument, Argument);
	int getPar(vector<int>&,vector<int>&,int , int, int, int);
	int getParT(vector<int>&,vector<int>&,int , int, int, int);
	int getChild(vector<int>&,vector<int>&,int , int, int);
	int getChildT(vector<int>&,vector<int>&,int , int, int);

	//Functions to get Next and Next*
	int getNext(vector<int>&, vector<int>&, Argument, Argument);
	int getNextT(vector<int>&, vector<int>&, Argument, Argument);
	int getNextafter(vector<int>&,vector<int>&,int , int, int, int);
	int getNextbefore(vector<int>&,vector<int>&,int , int, int);
	int getNextafterT(vector<int>&,vector<int>&,Argument, Argument);
	int getNextbeforeT(vector<int>&,vector<int>&,int , int, int);

	//Functions to get Affects and Affects*
	int getAffects(vector<int>&, vector<int>&, Argument, Argument);
	int getAffectsT(vector<int>& , vector<int>& , Argument , Argument);
	int getAffecting(vector<int>&,vector<int>&,Argument, Argument);
	int getAffectedby(vector<int>&,vector<int>&,int , int, int);
	int AffectsStarLong ( STATEMENT_INDEX s1, vector<STATEMENT_INDEX> &resVector2, vector<STATEMENT_INDEX> &resVector1,int t1,int t2,int type2,bool bothWay);
	BOOLEAN AffectsStarTLong ( STATEMENT_INDEX s1, vector<STATEMENT_INDEX> &resVector );
	BOOLEAN searchStmtList( STATEMENT_INDEX s1, vector<STATEMENT_INDEX> &searchVector, list<STATEMENT_INDEX>::iterator &it );
	
	//Functions to get Modify
	int getModify(vector<int>&,vector<int>&, Argument, Argument);
	int getModifies(vector<int>&,vector<int>&, int , int, int, int);
	int getModifiedBy(vector<int>&,vector<int>&, int , int, int, int);

	//Functions to get Uses
	int getUses(vector<int>&,vector<int>&, Argument, Argument);
	int getUsess(vector<int>&,vector<int>&, int , int, int, int);
	int getUsedBy(vector<int>&,vector<int>&, int , int, int, int);

	//Functions to get Calls and Calls*
	int getCalls(vector<int>&,vector<int>&, Argument, Argument);
	int getCallsT(vector<int>&,vector<int>&, Argument, Argument);
};

#endif